﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;
using System.Reflection;
using Water.Architecture2.Model;
using Water.Resources.Globalize;

namespace Water.Architecture2.EntityXML
{
    public class EntityXMLParser
    {
        public void Parse(string entityXmlFile)
        {
            if (File.Exists(entityXmlFile))
            {
                XmlReaderSettings setting = new XmlReaderSettings();
                try
                {
                    setting.IgnoreComments = true;
                    setting.IgnoreWhitespace = true;
                    setting.IgnoreProcessingInstructions = true;
                    using (XmlReader xmlReader = XmlReader.Create(entityXmlFile, setting))
                    {
                        EntityNode entityNode = null;
                        while (xmlReader.Read())
                        {
                            XmlNodeType noteType = xmlReader.NodeType;
                            switch (xmlReader.NodeType)
                            {
                                case XmlNodeType.Element:
                                    {
                                        String elementName = xmlReader.Name.ToLower();

                                        if (elementName == "entity")
                                        {
                                            entityNode = new EntityNode();
                                            CreateEntityNodeHelp(xmlReader, entityNode);
                                        }
                                        else if (elementName == "key-property")
                                        {
                                            PropertyNode propertyNode = CreatePropertyNodeHelp(xmlReader, PropertyNodeType.KeyProperty);
                                            entityNode.PropertyNodes.Add(propertyNode);
                                        }
                                        else if (elementName == "property")
                                        {
                                            PropertyNode propertyNode = CreatePropertyNodeHelp(xmlReader, PropertyNodeType.Property);
                                            entityNode.PropertyNodes.Add(propertyNode);
                                        }
                                        else if (elementName == "ref-property")
                                        {
                                            PropertyNode propertyNode = CreatePropertyNodeHelp(xmlReader, PropertyNodeType.RefProperty);
                                            entityNode.PropertyNodes.Add(propertyNode);
                                        }
                                        else if (elementName == "query-sql")
                                        {
                                            entityNode.Sql = xmlReader.ReadString().Replace("\n", "").Trim();
                                        }
                                    }
                                    break;
                                case XmlNodeType.EndElement:
                                    if (XmlNodeType.EndElement == noteType)
                                    {
                                        string endElementName = xmlReader.Name.ToLower();
                                        if (endElementName == "entity")
                                        {
                                            if (entityNode != null)
                                            {
                                                try
                                                {
                                                    EntityMapping entityMapping = new EntityMapping();
                                                    entityMapping.init(entityNode);
                                                    EntityMappingContainer.Add(entityNode.EntityClass, entityMapping);
                                                }
                                                catch (Exception e)
                                                {
                                                    throw e;
                                                }
                                                entityNode = null;
                                            }
                                        }
                                    }
                                    break;

                            }
                        }
                    }
                }
                catch (XmlException xe)
                {
                    throw xe;
                }
            }
            else
                throw new Exception(string.Format(ExceptionResource.ExceptionFileNotFound, entityXmlFile));
        }


        private void CreateEntityNodeHelp(XmlReader xmlReader, EntityNode entityNode)
        {
            for (int i = 0; i < xmlReader.AttributeCount; i++)
            {
                xmlReader.MoveToAttribute(i);
                switch (xmlReader.Name.ToLower())
                {
                    case "class":
                        entityNode.EntityClass = xmlReader.Value;
                        break;
                    case "table":
                        entityNode.Table = xmlReader.Value;
                        break;
                    case "view":
                        entityNode.View = xmlReader.Value;
                        break;
                    case "query-only":
                    case "queryonly":
                        entityNode.QueryOnly = bool.Parse(xmlReader.Value);
                        break;
                    case "connectionstring-name":
                    case "connection-string-name":
                    case "connectionstringname":
                        entityNode.ConnectionStringName = xmlReader.Value;
                        break;
                    case "default-orderby-express":
                    case "defaultorderbyexpress":
                        entityNode.DefaultOrderByExpress = xmlReader.Value;
                        break;
                    case "cache":
                        entityNode.Cache = bool.Parse(xmlReader.Value);
                        break;
                    case "dal-class":
                        entityNode.DalClass=xmlReader.Value;
                        break;
                    case "dal-assembly":
                        entityNode.DalAssembly = xmlReader.Value;
                        break;
                    case "sub-query":
                    case "subquery":
                        entityNode.Subquery = bool.Parse(xmlReader.Value);
                        break;
                }
            }
        }



        private PropertyNode CreatePropertyNodeHelp(XmlReader xmlReader, PropertyNodeType propertyNodeType)
        {
            PropertyNode propertyNode = new PropertyNode();
            propertyNode.NodeType = propertyNodeType;
            for (int i = 0; i < xmlReader.AttributeCount; i++)
            {
                xmlReader.MoveToAttribute(i);
                String attrName = xmlReader.Name.ToLower();
                String attrValue = xmlReader.Value;//.ToLower();

                if (attrName == "name")
                    propertyNode.Name = attrValue;
                else if (attrName == "column")
                    propertyNode.Column = attrValue;
                else if (attrName == "type")
                    propertyNode.Type = attrValue;
                else if (attrName == "generator-type")
                    propertyNode.GeneratorType = GeneratorTypeConvert.ToGeneratorType(attrValue);
                else if (attrName == "generator-name")
                    propertyNode.GeneratorName = attrValue;
                else if (attrName == "insert-ignore")
                    propertyNode.InsertIgnore = Boolean.Parse(attrValue);
                else if (attrName == "update-ignore")
                    propertyNode.UpdateIgnore = Boolean.Parse(attrValue);
                else if (attrName == "ref-entity")
                    propertyNode.RefEntity = attrValue;
                else if (attrName == "ref-property")
                    propertyNode.RefProperty = attrValue;
                else if (attrName == "ref-display-property")
                    propertyNode.RefDisplayProperty = attrValue;
                else if (attrName == "ref-mode")
                    propertyNode.RefMode = RefModeConvert.ToRefMode(attrValue);
                else if (attrName == "property")
                    propertyNode.Property = attrValue;
                else if (attrName == "prompt")
                    propertyNode.Prompt = attrValue;
            }
            return propertyNode;
        }
    }
}
